
#include <algorithm>

#include "core/common/Device.h"
#include "core/common/Packet.h"
#include "core/server/Controller.h"
#include "network/AbstractClient.h"
#include "network/Server.h"

Device::Device(Server *server)
    : pServer_(server), iX_(0), iY_(0), moveCount(0)
{
}

Device::~Device()
{
}

bool Device::command(const Controller* controller, CommandPacket* command)
{
    mutex_.lock();
    bool validController = (queue_.size() > 0 && queue_.front() == controller);
    mutex_.unlock();

    if(validController)
    {
        // Déplacer
        switch(command->param)
        {
        case Protocol::left:
            if(iX_ > -(gridSize / 2))
                iX_--;
            break;

        case Protocol::right:
            if(iX_ < (gridSize / 2))
                iX_++;
            break;

        case Protocol::up:
            if(iY_ < (gridSize / 2))
                iY_++;
            break;

        case Protocol::down:
            if(iY_ > (gridSize / 2))
                iY_--;
            break;
        }

        ++moveCount;

        // Réinitialiser si nécéssaire
        if(moveCount > moveLimit)
        {
            moveCount = 0;
            iX_ = 0;
            iY_ = 0;
        }

        // Mise à jour des clients
        UpdatePacket updatePacket;
        updatePacket.type = Protocol::update;
        updatePacket.x = iX_;
        updatePacket.y = iY_;
        return pServer_->broadcast(&updatePacket, sizeof(updatePacket));
    }

    return false;
}

bool Device::updateController()
{
    uint8_t data = Protocol::control;
    int w = 0;

    mutex_.lock();

    if(queue_.size() > 0)
        w = queue_.front()->write(&data, sizeof(data));

    mutex_.unlock();

    return w > 0;
}

bool Device::release(const Controller* controller)
{
    // Compter le nombre d'occurences de controller dans la file
    mutex_.lock();
    std::vector<Controller*>::iterator it = std::find(queue_.begin(), queue_.end(), controller);
    mutex_.unlock();

    // Vérification que le contrôleur est déjà dans la file
    if(it == queue_.end())
        return false;

    // Retirer de la file
    mutex_.lock();
    queue_.erase(it);
    mutex_.unlock();

    // Lorsque le contrôle est relâché, chercher un nouveau contrôleur
    return updateController();
}

bool Device::request(Controller* controller)
{
    // Compter le nombre d'occurences de controller dans la file
    mutex_.lock();
    int count = (int) std::count(queue_.begin(), queue_.end(), controller);
    mutex_.unlock();

    // Vérification que le contrôleur n'est pas déjà dans la file
    if(count != 0)
        return false;

    // Ajout à la file
    mutex_.lock();
    queue_.push_back(controller);
    mutex_.unlock();

    // Le contrôle est mis à jour si personne n'est là pour
    // indiquer qu'il relâche le contrôle
    if(queue_.size() == 1)
        return updateController();
}
